<template>
  <div
    class="comp-radio"
    :class="{
      'is-checked': isChecked,
      'is-disabled': isDisabled,
      'is-bordered': bordered,
      'is-button': button,
      [`comp-radio--${size}`]: size,
      'has-label': !!label || $slots.default
    }"
    @click="handleClick"
  >
    <div v-if="!button" class="comp-radio__icon">
      <div
        class="comp-radio__inner"
        :style="{ 'background-color': isChecked && !isDisabled ? checkedColor : '' }"
      ></div>
    </div>
    <div class="comp-radio__label">
      <slot>{{ label }}</slot>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { computed, inject, ref, type Ref } from 'vue';

  export interface RadioProps {
    modelValue?: string | number | boolean;
    value?: string | number | boolean;
    disabled?: boolean;
    label?: string;
    checkedColor?: string;
    size?: 'small' | 'medium' | 'large';
    bordered?: boolean;
    button?: boolean;
    name?: string;
  }

  export interface RadioEmits {
    (e: 'update:modelValue', value: string | number | boolean): void;
    (e: 'change', value: string | number | boolean): void;
    (e: 'click', event: Event): void;
  }

  export interface RadioGroupContext {
    modelValue?: string | number | boolean;
    disabled?: boolean;
    updateValue: (value: string | number | boolean) => void;
    name?: string;
  }

  export interface RadioInstance {
    isChecked: boolean;
    setChecked: () => void;
  }

  const props = withDefaults(defineProps<RadioProps>(), {
    modelValue: undefined,
    value: '',
    disabled: false,
    label: '',
    checkedColor: '#2979ff',
    size: 'medium',
    bordered: false,
    button: false,
    name: ''
  });

  const emit = defineEmits<RadioEmits>();

  // 注入radioGroup上下文
  const radioGroup = inject<Ref<RadioGroupContext> | undefined>('radioGroup', undefined);

  // 计算是否选中
  const isChecked = computed(() => {
    if (radioGroup) {
      return radioGroup.value.modelValue === props.value;
    }
    return props.modelValue === props.value;
  });

  // 计算是否禁用
  const isDisabled = computed(() => {
    if (radioGroup) {
      return radioGroup.value.disabled || props.disabled;
    }
    return props.disabled;
  });

  // 处理点击事件
  const handleClick = (event: Event) => {
    if (isDisabled.value) return;

    const value = props.value;

    if (radioGroup) {
      radioGroup.value.updateValue(value);
    } else {
      emit('update:modelValue', value);
      emit('change', value);
    }

    emit('click', event);
  };

  // 设置选中状态
  const setChecked = () => {
    if (isDisabled.value) return;
    
    const value = props.value;
    
    if (radioGroup) {
      radioGroup.value.updateValue(value);
    } else {
      emit('update:modelValue', value);
      emit('change', value);
    }
  };

  // 暴露组件实例方法
  defineExpose({
    isChecked,
    setChecked
  });
</script>

<style lang="scss" scoped>
  .comp-radio {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
    margin-right: 16px;
    font-size: 14px;
    line-height: 1;
    user-select: none;

    &__icon {
      position: relative;
      width: var(--radio-size, 20px);
      height: var(--radio-size, 20px);
      border: 1px solid var(--radio-border-color, #c8c9cc);
      border-radius: 50%;
      background-color: var(--radio-background-color, #fff);
      box-sizing: border-box;
      transition: all 0.2s;
    }

    &__inner {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 0;
      height: 0;
      border-radius: 50%;
      background-color: var(--radio-checked-color, #2979ff);
      transition: all 0.2s;
    }

    &__label {
      margin: var(--radio-label-margin, 0 0 0 8px);
      color: var(--radio-label-color, #333);
      line-height: 1.2;
    }

    &.is-checked {
      .comp-radio__icon {
        border-color: var(--radio-checked-color, #2979ff);
      }

      .comp-radio__inner {
        width: calc(var(--radio-size, 20px) - 8px);
        height: calc(var(--radio-size, 20px) - 8px);
      }

      &.is-button {
        color: #fff;
        background-color: var(--radio-checked-color, #2979ff);
        border-color: var(--radio-checked-color, #2979ff);
      }
    }

    &.is-disabled {
      cursor: not-allowed;

      .comp-radio__icon {
        border-color: var(--radio-disabled-color, #c8c9cc);
        background-color: #f5f7fa;
      }

      .comp-radio__inner {
        background-color: var(--radio-disabled-color, #c8c9cc);
      }

      .comp-radio__label {
        color: var(--radio-disabled-label-color, #c8c9cc);
      }

      &.is-button {
        color: #c8c9cc;
        background-color: #f5f7fa;
        border-color: #e4e7ed;
      }
    }

    &.is-bordered {
      padding: 8px 15px;
      border-radius: 4px;
      border: 1px solid var(--radio-border-color, #c8c9cc);

      &.is-checked {
        border-color: var(--radio-checked-color, #2979ff);
      }

      &.is-disabled {
        border-color: #e4e7ed;
      }
    }

    &.is-button {
      padding: 8px 15px;
      border-radius: 4px;
      border: 1px solid var(--radio-border-color, #c8c9cc);
      background-color: #fff;
      transition: all 0.2s;

      .comp-radio__icon {
        display: none;
      }

      .comp-radio__label {
        margin: 0;
      }
    }

    &--small {
      font-size: 12px;

      .comp-radio__icon {
        --radio-size: 16px;
      }

      &.is-bordered, &.is-button {
        padding: 5px 12px;
      }
    }

    &--large {
      font-size: 16px;

      .comp-radio__icon {
        --radio-size: 24px;
      }

      &.is-bordered, &.is-button {
        padding: 10px 20px;
      }
    }
  }
</style>